/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#include "MaCI_PlayerMainFrame.h"

MaCI_PlayerMainFrame::MaCI_PlayerMainFrame( wxWindow* parent )
:
  MainFrame( parent ),
  iPlayerModuleGenerator(),
  iPlaying (false),
  iPlayingSpeed(1.0),
  iGimi(NULL),
  iMaCICtrlServer(NULL),
  iPlayer(),
  iVersionNumber("1.8.1"),
  iRangingMinor(0),
  iPositionMinor(0),
  iSpeedCtrlMinor(0),
  iIMUMinor(0),
  iEnergyMinor(0),
  iWirelessMinor(0),
  iCoordinateDriveMinor(0)
  
{
  m_listCtrl_Services->InsertColumn(0,wxT("MaCI group: MaCI_Player"));
  m_listCtrl_Services->SetColumnWidth(0, 300);
  m_listCtrl_Services->InsertColumn(1,wxT("Start Time"));
  m_listCtrl_Services->SetColumnWidth(1, 100);
  m_listCtrl_Services->InsertColumn(2,wxT("End Time"));
  m_listCtrl_Services->SetColumnWidth(2, 100);
  wxTimer::Start(200);
}
//*****************************************************************************

MaCI_PlayerMainFrame::~MaCI_PlayerMainFrame()
{
  iPlayer.StopPlaying();
  wxTimer::Stop();
}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnLoadLogFile( wxCommandEvent& event )
{
  wxFileDialog fd(this,"Choose a log file(s)","","","*.txt",wxFD_OPEN | wxFD_FILE_MUST_EXIST|wxMULTIPLE|wxCHANGE_DIR);
  wxArrayString chosenFileNames;
  wxArrayString fileNames;

  int r=fd.ShowModal();
  if (r==wxID_OK)
  {
    fd.GetPaths(chosenFileNames);
    fd.GetFilenames(fileNames);
    
    for(int i = 0; i < chosenFileNames.Count(); i++){

      //Getting filename.
      std::string filename = std::string(chosenFileNames[i].mb_str());
      std::string name="";    
      int index;
      PlayerModule *pModule = iPlayerModuleGenerator.GenerateNewPlayerModule(filename,iMaCICtrlServer);

      /*
      //Read the first line of file and choose the right playerModule to construct
      FILE *file= fopen(chosenFileNames[i].mb_str(),"rt");
      char c[200] = "";
      fgets (c, 200,file );
      std::string firstLine(c);
      dPrint(10,"c '%s',first line '%s'",c,firstLine.c_str());
      
      //////////////////////////////////////////////////////
      //////////////////////////////////////////////////////
      ///////////CONSTRUCT HERE YOUR PLAYER MODULE//////////
      //////////////////////////////////////////////////////
      //////////////////////////////////////////////////////

      //////////////////////////////////////////////////////
      //////////////////RANGING FILE////////////////////////
      //////////////////////////////////////////////////////
      if(firstLine.compare("%MaCI_Ranging log file\n") == 0){
        //Create module and add it to player
        MaCI::Ranging::CRangingServer *rServer = new MaCI::Ranging::CRangingServer(iMaCICtrlServer,iRangingMinor);
        iRangingMinor++;
        RangingFilePlayer *rfplayer = new RangingFilePlayer(rServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(rfplayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"Ranging file found!Created ranging File player");

      //////////////////////////////////////////////////////
      //////////////////POSITION FILE///////////////////////
      //////////////////////////////////////////////////////
      }else if(firstLine.compare(0,23,"%MaCI_Position log file") == 0){

        //Create module and add it to player
        MaCI::Position::CPositionServer *pServer = new MaCI::Position::CPositionServer(iMaCICtrlServer,iPositionMinor);
        iPositionMinor++;
        PositionFilePlayer *pfplayer = new PositionFilePlayer(pServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(pfplayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"Position file found!Created position File player");

      //////////////////////////////////////////////////////
      //////////////////SPEEDCTRL FILE//////////////////////
      //////////////////////////////////////////////////////
      }else if(firstLine.compare("%MaCI_SpeedCtrl log file\n") == 0){
        //Create module and add it to player
        MaCI::SpeedCtrl::CSpeedCtrlServer *sServer = new MaCI::SpeedCtrl::CSpeedCtrlServer(iMaCICtrlServer,iSpeedCtrlMinor);
        iSpeedCtrlMinor++;
        SpeedCtrlFilePlayer *sfplayer = new SpeedCtrlFilePlayer(sServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(sfplayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"SpeedCtrl file found!Created speedctrl file player");

      //////////////////////////////////////////////////////
      //////////////////IMU FILE////////////////////////////
      //////////////////////////////////////////////////////
      }else if(firstLine.compare("%MaCI_IMU log file\n") == 0){
        //Create module and add it to player
        MaCI::IMU::CIMUServer *iServer = new MaCI::IMU::CIMUServer(iMaCICtrlServer,iIMUMinor);
        iIMUMinor++;
        IMUFilePlayer *ifplayer = new IMUFilePlayer(iServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(ifplayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"IMU file found!Created IMU file player");

      //////////////////////////////////////////////////////
      //////////////////ENERGY FILE/////////////////////////
      //////////////////////////////////////////////////////
      }else if(firstLine.compare("%MaCI_Energy log file\n") == 0){
        //Create module and add it to player
        MaCI::Energy::CEnergyServer *eServer = new MaCI::Energy::CEnergyServer(iMaCICtrlServer,iEnergyMinor);
        iEnergyMinor++;
        EnergyFilePlayer *efplayer = new EnergyFilePlayer(eServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(efplayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"Energy file found!Created energy file player");

      //////////////////////////////////////////////////////
      //////////////////WIRELESS FILE///////////////////////
      //////////////////////////////////////////////////////
      }else if(firstLine.compare("%MaCI_Wireless log file\n") == 0){
        //Create module and add it to player
        MaCI::Wireless::CWirelessServer *wServer = new MaCI::Wireless::CWirelessServer(iMaCICtrlServer,iWirelessMinor);
        iWirelessMinor++;
        WirelessFilePlayer *wfplayer = new WirelessFilePlayer(wServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(wfplayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"Wireless file found!Created wireless file player");
      //////////////////////////////////////////////////////
      //////////////////COORDINATEDRIVE FILE////////////////
      //////////////////////////////////////////////////////
      }else if(firstLine.compare("%MaCI_CoordinateDrive log file\n") == 0){
        //Create module and add it to player
        MaCI::CoordinateDrive::CCoordinateDriveServer *cServer = new MaCI::CoordinateDrive::CCoordinateDriveServer(iMaCICtrlServer,iCoordinateDriveMinor);
        iCoordinateDriveMinor++;
        CoordinateDriveFilePlayer *cfplayer = new CoordinateDriveFilePlayer(cServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(cfplayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"CoordinateDrive file found!Created CoordinateDrive file player");

      //////////////////////////////////////////////////////
      //////////////////IMAGE FILE//////////////////////////
      //////////////////////////////////////////////////////
      }else if(firstLine.compare("%MaCI_Image log file\n") == 0){
        //Create module and add it to player
        MaCI::Image::CImageServer *imageServer = new MaCI::Image::CImageServer(iMaCICtrlServer,iImageMinor);
        iImageMinor++;
        ImageFilePlayer *imagePlayer = new ImageFilePlayer(imageServer,std::string(chosenFileNames[i].mb_str()));
        pModule =static_cast<PlayerModule *>(imagePlayer);
        iPlayer.SetPlayerModule(pModule);
        dPrint(3,"Image file found!Created Image file player");


      }else{
        dPrint(1,"Didn't recognize file '%s'.. ignoring.",chosenFileNames[i].mb_str());
        continue;
      }
      //////////////////////////////////////////////////////
      //////////////////////////////////////////////////////
      //////////////////////////////////////////////////////
      //////////////////////////////////////////////////////
      //////////////////////////////////////////////////////
      //////////////////////////////////////////////////////

      */
      if(pModule){
        iPlayer.SetPlayerModule(pModule);
        //Then add module to list
        name = pModule->GetName();
        int numberOfItems = m_listCtrl_Services->GetItemCount();
        index = m_listCtrl_Services->InsertItem(numberOfItems,name);
        m_listCtrl_Services->SetItemPtrData(index,(wxUIntPtr)pModule);
        
        //Set colour to red..
        wxColour red(255,0,0);
        wxColour green(0,255,0);
        if(iPlayer.IsPlaying()){
          m_listCtrl_Services->SetItemTextColour(index,green);
        }else{
          m_listCtrl_Services->SetItemTextColour(index,red);
        }
      }

    }
  
    //Then check total playing times...
    CheckModuleTimes();
    CheckTotalTime();

   


  }

  

	
}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnQuit( wxCommandEvent& event )
{
  
  this->Destroy();
}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnAbout( wxCommandEvent& event )
{
  MaCI_PlayerAbout_Dialog dia(this,iVersionNumber);
  dia.ShowModal();
	
}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnListItemSelected( wxListEvent& event )
{
	// TODO: Implement OnListItemSelected
}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnListItemRClick( wxListEvent& event )
{
  int item = event.GetIndex();
  wxPoint position = event.GetPoint();

  if(item >=0 && item < m_listCtrl_Services->GetItemCount()){
    //Create menu and menuitem for removing PlayerModule
    wxMenu *menu = new wxMenu();
    wxMenuItem *removeItem =  menu->InsertCheckItem(0,0,"Remove");
    if(iPlayer.IsPlaying()){
      removeItem->Enable(false);

    }
    PopupMenu(menu,position.x,position.y);

    //If user wants to remove item
    if(removeItem->IsChecked()){
      dPrint(3,"Removing player module");
      PlayerModule *p = reinterpret_cast<PlayerModule *>(m_listCtrl_Services->GetItemData(item));
      iPlayer.RemovePlayerModule(p);
      delete(p);
      m_listCtrl_Services->DeleteItem(item);

      //Then update UI times.
      CheckModuleTimes();
      CheckTotalTime();
    }
  
    //remove and delete the menu
    menu->Remove(removeItem);
    delete(removeItem);
    delete(menu);

   
  }


}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnSliderScroll( wxScrollEvent& event )
{
  float ratio = (float)event.GetPosition()/(float)m_slider_time->GetMax();

  int secAfterBeginning = iTotalTime.getSeconds()*ratio;
  gim::time begin,end;

  if(iPlayer.GetTimeLimits(begin,end)){
    begin.addTimeMs(secAfterBeginning*1000);

    iPlayer.SetCurrentTime(begin);
  
    gim::time t;
    float ratio;
    wxString totalTime;
    iPlayer.GetCurrentTime(t,ratio);
    totalTime = GetStringOfTime(t);
    
    m_staticText_currentTime->SetLabel(totalTime);
  }

}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnPlayButtonClick( wxCommandEvent& event )
{
  int numberOfItems = m_listCtrl_Services->GetItemCount();
  if(numberOfItems){
    if(!iPlayer.IsPlaying()){
      iPlayer.StartPlaying();
          
    }else{
      iPlayer.PausePlaying();
      
    }
  }
}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnStopButtonClick( wxCommandEvent& event )
{

  int numberOfItems = m_listCtrl_Services->GetItemCount();
 
  iPlayer.StopPlaying();
 


}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnSlowerButtonClick( wxCommandEvent& event )
{
  if(iPlayingSpeed > MIN_SPEED){
     iPlayingSpeed = iPlayingSpeed/2;

     iPlayer.SetPlayingSpeed(iPlayingSpeed);
     wxString s;
     s << "Playing speed "<<iPlayingSpeed <<"x";
     m_statusBar1->SetStatusText(s);
  }

}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnFasterButtonClick( wxCommandEvent& event )
{  
  if(iPlayingSpeed < MAX_SPEED){
    iPlayingSpeed = iPlayingSpeed*2;
    iPlayer.SetPlayingSpeed(iPlayingSpeed);
    wxString s;
    s << "Playing speed "<<iPlayingSpeed <<"x";
    m_statusBar1->SetStatusText(s);
  }
	
}
//*****************************************************************************

void MaCI_PlayerMainFrame::OnServiceAssignment(const Gimbo::TServiceAssignmentList &aServiceList)
{
  //Do nothing :)


}  

//*****************************************************************************

void MaCI_PlayerMainFrame::OnSetMaCIGroupName( wxCommandEvent& event )
{
  std::string maciGroupName;
  MaCI_PlayerGet_Name gn(this,&maciGroupName);

  gn.ShowModal();
  if(maciGroupName.length() > 0){
    iMaCICtrlServer->SetGroupName(maciGroupName);
    wxString s = "MaCI group: " + wxString(maciGroupName);
    wxListItem lItem;
    lItem.SetText(s);
    
    m_listCtrl_Services->SetColumn(0,lItem);
  }
 
 

}
//*****************************************************************************
void MaCI_PlayerMainFrame::OnRepeatButtonClick( wxCommandEvent& event )
{

  if(iPlayer.IsRepeat()){
    iPlayer.SetRepeat(false);
    m_bpButton_Repeat->SetBitmapLabel(wxBitmap( wxT("images/playOneTime.bmp")));
  }else{
    iPlayer.SetRepeat(true);
    m_bpButton_Repeat->SetBitmapLabel(wxBitmap( wxT("images/repeat.bmp")));
  }

}
//*****************************************************************************

bool MaCI_PlayerMainFrame::Initialize(gimi::GIMI *aGimiPtr,int aGimboID, int aReportID)
{

  bool result = true;
  
  // Store for future reference.
  iGimi = aGimiPtr;
  iMaCICtrlServer = new MaCI::MaCICtrl::CMaCICtrlServer(aGimiPtr);
  
  iMaCICtrlServer->SetGroupName("MaCI_Player");
  // Start the Gimbo core.
  CComponent::Start(aGimiPtr, aGimboID, aReportID);
  wxString s;
  s << "Playing speed "<<iPlayingSpeed <<"x";
  m_statusBar1->SetStatusText(s);
}
//*****************************************************************************

void MaCI_PlayerMainFrame::Deinitialize(void)
{


}
//*****************************************************************************
void MaCI_PlayerMainFrame::CheckTotalTime(){

  gim::time begin,end;
  
  if(iPlayer.GetTimeLimits(begin,end)){
 
    iTotalTime = end-begin;
    wxString totalTime  = GetStringOfTime(iTotalTime);

    m_staticText_totalTime->SetLabel(totalTime);
  }else{
    wxString totalTime("0:00");
    m_staticText_totalTime->SetLabel(totalTime);
    m_staticText_currentTime->SetLabel(totalTime);
  }
}
//*****************************************************************************

void MaCI_PlayerMainFrame::CheckModuleTimes()
{
  gim::time beginTime,beginTimeModule,beginTimePlayer,endTime,endTimeModule,endTimePlayer;
  //Calculate player modules begin and end time...
  iPlayer.GetTimeLimits(beginTimePlayer,endTimePlayer);
  
  GetStringOfTime(endTimePlayer);
  for(int j = 0; j < m_listCtrl_Services->GetItemCount();j++){
    PlayerModule *p = reinterpret_cast<PlayerModule *>(m_listCtrl_Services->GetItemData(j));
    p->GetTimeLimits(beginTimeModule, endTimeModule);
    dPrint(10,"times. %d %d %d %d", beginTimeModule.getSeconds(),beginTimeModule.getUSeconds(),endTimeModule.getSeconds(),endTimeModule.getUSeconds());
    if(beginTimeModule.getSeconds() != 0 ||beginTimeModule.getUSeconds() != 0||
       endTimeModule.getSeconds() != 0 || endTimeModule.getUSeconds() != 0){
      beginTime = beginTimeModule -beginTimePlayer;
      
      endTime = endTimeModule- beginTimePlayer;
      wxString end =  GetStringOfTime(endTime);
      wxString begin =  GetStringOfTime(beginTime);
      dPrint(10,"Setting %s begin and %s to end",begin.c_str(),end.c_str());
      m_listCtrl_Services->SetItem(j,1,begin);
      m_listCtrl_Services->SetItem(j,2,end);
    }else{
      //Begin and ending time zero (no action...)
      wxString end = "00:00";
      wxString begin = "00:00";
      m_listCtrl_Services->SetItem(j,1,begin);
      m_listCtrl_Services->SetItem(j,2,end);

    }
  }
  
}
//*****************************************************************************
void MaCI_PlayerMainFrame::Notify()
{
  //dPrint(1,"Notify()");
  //Gets the current time and sets value to GUI
  if( m_listCtrl_Services->GetItemCount() > 0){
    gim::time t;
    float ratio;
   
    iPlayer.GetCurrentTime(t,ratio);
    wxString totalTime = GetStringOfTime(t);
    
    m_staticText_currentTime->SetLabel(totalTime);
    
    //dPrint(1,"Setting value to %d",(int)(ratio*m_slider_time->GetMax()));
    m_slider_time->SetValue((int)(ratio*m_slider_time->GetMax()));


  }
  //dPrint(1,"Checking if playing %d %d",iPlayer.IsPlaying(), iPlaying);
  //Check if playing mode is changed
  if(iPlayer.IsPlaying() != iPlaying){
    iPlaying = iPlayer.IsPlaying();  
    //Change the play/pause button image
    if(!iPlaying){
      //  dPrint(1,"Setting pause image");
      m_bpButton_Play->SetBitmapLabel(wxBitmap( wxT("images/pause.bmp")));
    }else{
      //dPrint(1,"Setting play image");
      m_bpButton_Play->SetBitmapLabel(wxBitmap( wxT("images/play.bmp")));
    }

    //Set colour to red or green
    wxColour red(255,0,0);
    wxColour green(0,255,0);
    for(int index = 0; index <m_listCtrl_Services->GetItemCount(); index++){
      if(iPlaying){
        m_listCtrl_Services->SetItemTextColour(index,green);
      }else{
        m_listCtrl_Services->SetItemTextColour(index,red);
      }
    }
  }
    
}
//*****************************************************************************
wxString MaCI_PlayerMainFrame::GetStringOfTime(gim::time aTime){
  wxString totalTime;
  
  struct tm aTm;
  aTime.getLocalTime(aTm);
  if(aTime.getSeconds()> 60*60){
    long int sec = aTime.getSeconds();
    
    sec = sec /3600;
    totalTime << sec <<":";
  }
  if(aTm.tm_min < 10){
    totalTime << "0" <<aTm.tm_min <<":";
  }else{
    totalTime <<aTm.tm_min <<":";
  }
  
  if(aTm.tm_sec <10){
    totalTime << "0" <<aTm.tm_sec;
  }else{
    totalTime << aTm.tm_sec;
  }

  return totalTime;
}
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
